package example

import (
	"gitee.com/Luna-CY/Golang-Project-Template/entry/http/request"
	"gitee.com/Luna-CY/Golang-Project-Template/entry/http/response"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/context"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/context/contextutil"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/errors"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/i18n"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/interface/dao"
	"gitee.com/Luna-CY/Golang-Project-Template/internal/interface/service"
	"gitee.com/Luna-CY/Golang-Project-Template/model"
	"github.com/gin-gonic/gin"
)

type UpdateRequest struct {
	Id      string `json:"id" validate:"required" binding:"required"`                                                  // record id
	Name    string `json:"name" validate:"required" maximum:"255" binding:"required,max=255"`                          // 字符串字段
	Value   uint64 `json:"value" validate:"required" minimum:"1" maximum:"999999" binding:"required,min=1,max=999999"` // 数值字段
	Enable  bool   `json:"enable" validate:"optional" binding:"omitempty"`                                             // 布尔字段
	Type    int    `json:"type" validate:"required" enums:"1,2,3" binding:"required,oneof=1 2 3"`                      // 枚举字段, enums: 1 - A, 2 - B, 3 - C
	ImageId string `json:"image_id" validate:"optional" binding:"omitempty"`                                           // 文件字段
}

// Update Update
// @tags category/example
// @summary update
// @param param body UpdateRequest true "request body"
// @success 200 {object} response.Response{} "successful. click to expand response structure"
// @router /example/update [post]
func (cls *Example) Update(c *gin.Context) (response.Code, any, errors.I18nError) {
	var body = UpdateRequest{}
	if err := request.ShouldBindJSON(c, &body); nil != err {
		return response.InvalidParams, nil, errors.NewI18n(i18n.CommonIdInvalidRequest, err.Relation(errors.ErrorInvalidRequest("SHGWHE_LE.E_LE.U_TE.313038", "参数错误")))
	}

	var ctx = contextutil.NewContextWithGin(c)

	example, err := cls.example.GetExampleByCondition(ctx, dao.BusinessExampleOptionWithId(body.Id))
	if nil != err {
		if err.IsType(errors.ErrorTypeRecordNotFound) {
			return response.InvalidParams, nil, errors.NewI18n(i18n.CommonIdRecordNotFound, err.Relation(errors.New(errors.ErrorTypeInvalidRequest, "SHGWHE_LE.E_LE.U_TE.383049", "example record not found: %s", body.Id)))
		}

		return response.ServerInternalError, nil, errors.NewI18n(i18n.CommonIdServerInternalError, err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.413052", "获取数据失败")))
	}

	var oldImageId = *example.ImageId

	// if need transaction
	//if err := cls.example.WithTransaction(ctx, func(ctx context.Context) errors.Error {
	//	if err := cls.example.UpdateExample(ctx, example, pointer.New(body.Field1), pointer.New(body.Field2), pointer.New(body.Field3), pointer.New(model.ExampleEnumFieldType(body.Field4))); nil != err {
	//		return err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.47"))
	//	}
	//
	//	return nil
	//}); nil != err {
	//	return response.ServerInternalError, nil, err
	//}

	var fields = []service.BusinessExampleField{
		service.BusinessExampleFieldWithName(body.Name),
		service.BusinessExampleFieldWithValue(body.Value),
		service.BusinessExampleFieldWithEnable(body.Enable),
		service.BusinessExampleFieldWithType(model.BusinessExampleEnumFieldType(body.Type)),
		service.BusinessExampleFieldWithImageId(nil),
	}

	if "" != body.ImageId {
		// 删除最后一个元素
		fields = fields[:len(fields)-1]

		image, err := cls.storage.GetObjectByCondition(ctx, dao.SystemObjectOptionWithId(body.ImageId), dao.SystemObjectOptionWithStatus(model.SystemObjectStatusUploaded))
		if nil != err {
			if err.IsType(errors.ErrorTypeRecordNotFound) {
				return response.InvalidParams, nil, errors.NewI18n(i18n.CommonIdRecordNotFound, err.Relation(errors.New(errors.ErrorTypeInvalidRequest, "SHGWHE_LE.E_LE.U_TE.492000", "文件不存在")))
			}

			return response.ServerInternalError, nil, errors.NewI18n(i18n.CommonIdServerInternalError, err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.522008", "获取文件失败")))
		}

		if oldImageId != image.Id {
			if err := cls.storage.PersistenceObject(ctx, image); nil != err {
				return response.ServerInternalError, nil, errors.NewI18n(i18n.CommonIdServerInternalError, err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.791130", "保存文件失败")))
			}
		}

		fields = append(fields, service.BusinessExampleFieldWithImageId(image))
	}

	if err := cls.example.WithTransaction(ctx, func(ctx context.Context) errors.Error {
		if err := cls.example.UpdateExample(ctx, example, fields...); nil != err {
			return err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.905422", "更新数据失败"))
		}

		// 如果旧图片id和新的图片id不一致，则删除旧图片
		if "" != oldImageId && oldImageId != body.ImageId {
			oldImage, err := cls.storage.GetObjectByCondition(ctx, dao.SystemObjectOptionWithId(oldImageId))
			if nil != err {
				return err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.975511", "获取文件失败"))
			}

			if err := cls.storage.CancelPersistenceObject(ctx, oldImage); nil != err {
				return err.Relation(errors.ErrorServerInternalError("SHGWHE_LE.E_LE.U_TE.1015548", "更新文件数据失败"))
			}
		}

		return nil
	}); nil != err {
		return response.ServerInternalError, nil, errors.NewI18n(i18n.CommonIdServerInternalError, err)
	}

	return response.Ok, nil, nil
}
